﻿using System;
using System.Collections.Generic;

using System.Text;

namespace smp.ButterflyCakes.Models
{
    public class SelectItem
    {
        private bool _usePleaseSelect;

        public SelectItem(string elementId)
        {
            ElementId = elementId;
            Options = new List<SelectOption>();
        }

        public SelectItem(string elementId, IEnumerable<SelectOption> options)
        {
            ElementId = elementId;
            Options = new List<SelectOption>();
            AddOptions(options);
        }

        public SelectItem(string elementId, Type enumType, object selectedValue)
        {
            ElementId = elementId;
            Options = new List<SelectOption>();
            foreach(var value in Enum.GetValues(enumType))
            {
                var isSelected = selectedValue != null && (int)selectedValue == (int) value;
                Options.Add(new SelectOption(((Enum) value).GetDescription(), (int) value, isSelected));
            }
        }

        public SelectItem(string elementId, Type enumType, object selectedValue, int ignoreValue)
        {
            ElementId = elementId;
            Options = new List<SelectOption>();
            foreach (var value in Enum.GetValues(enumType))
            {
                if (ignoreValue == ((int)value))
                    continue;
                var isSelected = selectedValue != null && (int)selectedValue == (int)value;
                Options.Add(new SelectOption(((Enum)value).GetDescription(), (int)value, isSelected));
            }
        }

        public SelectItem(string elementId, Type enumType, object selectedValue, List<int> ignoreValues)
        {
            ElementId = elementId;
            Options = new List<SelectOption>();
            foreach (var value in Enum.GetValues(enumType))
            {
                if(ignoreValues != null && ignoreValues.Count > 0 && ignoreValues.Contains((int)value))
                    continue;
                var isSelected = selectedValue != null && (int)selectedValue == (int)value;
                Options.Add(new SelectOption(((Enum)value).GetDescription(), (int)value, isSelected));
            }
        }

        public SelectItem(string elementId, bool usePleaseSelect)
        {
            ElementId = elementId;
            Options = new List<SelectOption>();
            _usePleaseSelect = usePleaseSelect;
        }

        public SelectItem(string elementId, bool usePleaseSelect, IEnumerable<SelectOption> options)
        {
            ElementId = elementId;
            Options = new List<SelectOption>();
            AddOptions(options);
            _usePleaseSelect = usePleaseSelect;
        }

        public SelectItem(string elementId, Type enumType, object selectedValue, bool usePleaseSelect)
        {
            ElementId = elementId;
            Options = new List<SelectOption>();
            foreach (var value in Enum.GetValues(enumType))
            {
                var isSelected = selectedValue != null && (int)selectedValue == (int)value;
                Options.Add(new SelectOption(((Enum)value).GetDescription(), (int)value, isSelected));
            }
            _usePleaseSelect = usePleaseSelect;
        }

        public SelectItem(string elementId, Type enumType, object selectedValue, int ignoreValue, bool usePleaseSelect)
        {
            ElementId = elementId;
            Options = new List<SelectOption>();
            foreach (var value in Enum.GetValues(enumType))
            {
                if (ignoreValue == (int)value)
                    continue;
                var isSelected = selectedValue != null && (int)selectedValue == (int)value;
                Options.Add(new SelectOption(((Enum)value).GetDescription(), (int)value, isSelected));
            }
            _usePleaseSelect = usePleaseSelect;
        }

        public SelectItem(string elementId, Type enumType, object selectedValue, List<int> ignoreValues, bool usePleaseSelect)
        {
            ElementId = elementId;
            Options = new List<SelectOption>();
            foreach (var value in Enum.GetValues(enumType))
            {
                if (ignoreValues != null && ignoreValues.Count > 0 && ignoreValues.Contains((int)value))
                    continue;
                var isSelected = selectedValue != null && (int)selectedValue == (int)value;
                Options.Add(new SelectOption(((Enum)value).GetDescription(), (int)value, isSelected));
            }
            _usePleaseSelect = usePleaseSelect;
        }

        public string ElementId { get; set; }
        public string ClassString { get; set; }
        public List<SelectOption> Options { get; set; }

        public SelectOption Selected
        {
            get
            {
                if (Options == null)
                    return null;
                return Options.Find(x => x.IsSelected);
            }
        }

        public string Html
        {
            get
            {
                if(Selected == null && _usePleaseSelect)
                {
                    Options.Insert(0, new SelectOption("Please Select", null));
                }
                var html = new StringBuilder("<select");
                if(!string.IsNullOrEmpty(ClassString))
                {
                    html.AppendFormat(" class=\"{0}\"", ClassString);
                }
                html.AppendFormat(" id=\"{0}\" name=\"{0}\">", ElementId);
                foreach(var option in Options)
                {
                    html.Append(option.Html);
                }
                html.Append("</select>");
                return html.ToString();
            }
        }

        public SelectItem AddOption(SelectOption option)
        {
            Options.Add(option);
            return this;
        }

        public SelectItem AddOptions(IEnumerable<SelectOption> options)
        {
            foreach(var option in options)
            {
                Options.Add(option);
            }
            return this;
        }

        public SelectItem SetSelected(object value)
        {
            foreach(var option in Options)
            {
                if(option.Value == value.ToString())
                {
                    option.IsSelected = true;
                }
                else
                {
                    option.IsSelected = false;
                }
                option.SetOption();
            }
            return this;
        }

        public SelectItem SetSelected(string name)
        {
            foreach (var option in Options)
            {
                if (option.Name == name)
                {
                    option.IsSelected = true;
                }
                else
                {
                    option.IsSelected = false;
                }
                option.SetOption();
            }
            return this;
        }

        public SelectItem AddClass(string cssClass)
        {
            if (!string.IsNullOrEmpty(ClassString))
                ClassString += " ";
            ClassString += cssClass;
            return this;
        }

        public SelectItem SetElementId(string elementId)
        {
            if(!string.IsNullOrEmpty(elementId))
            {
                ElementId = elementId;
            }
            return this;
        }

        public SelectItem UsePleaseSelect()
        {
            _usePleaseSelect = true;
            return this;
        }
    }

    public class SelectOption
    {
        private readonly Dictionary<string, string> _attributes = new Dictionary<string, string>();

        public SelectOption(string name, object value)
        {
            Name = name;
            if (value == null)
                value = "";
            Value = value.ToString();
            SetOption();
        }

        public SelectOption(string name, object value, string toolTip)
        {
            Name = name;
            if (value == null)
                value = "";
            Value = value.ToString();
            ToolTip = toolTip;
            SetOption();
        }

        public SelectOption(string name, object value, bool isSelected)
        {
            Name = name;
            if (value == null)
                value = "";
            Value = value.ToString();
            IsSelected = isSelected;
            SetOption();
        }

        public SelectOption(string name, object value, bool isDisabled, string toolTip)
        {
            Name = name;
            if (value == null)
                value = "";
            Value = value.ToString();
            IsDisabled = isDisabled;
            ToolTip = toolTip;
            SetOption();
        }

        public SelectOption(string name, object value, bool isSelected, bool isDisabled, string toolTip)
        {
            Name = name;
            if (value == null)
                value = "";
            Value = value.ToString();
            IsSelected = isSelected;
            IsDisabled = isDisabled;
            ToolTip = toolTip;
            SetOption();
        }

        public void AddCustomAttribute(string name, string value)
        {
            if(_attributes.ContainsKey(name))
            {
                _attributes.Remove(name);
            }
            _attributes.Add(name, value);
            SetOption();
        }

        public string Name { get; set; }
        public string Value { get; set; }
        public bool IsSelected { get; set; }
        public bool IsDisabled { get; set; }
        public string ToolTip { get; set; }
        public string Html { get; private set; }
        
        internal void SetOption()
        {
            var option = new StringBuilder("<option");
            if (IsSelected)
            {
                option.Append(" selected=\"selected\"");
            }
            if (!string.IsNullOrEmpty(ToolTip))
            {
                option.AppendFormat(" data-toggle=\"tooltip\" title=\"{0}\"", ToolTip);
            }
            if (IsDisabled)
            {
                option.Append(" disabled=\"disabled\" style=\"color: darkred;\"");
            }
            foreach(var attribute in _attributes)
            {
                option.AppendFormat(" {0}=\"{1}\"", attribute.Key, attribute.Value);
            }
            option.AppendFormat(" value=\"{0}\">{1}</option>", Value, Name);
            Html = option.ToString();
        }
    }
}
